package org.dromara.common.redis.aspect;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.dromara.common.core.service.ComboboxService;
import org.dromara.common.redis.annotation.CacheCombobox;
import org.dromara.common.redis.utils.CacheUtils;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

@Slf4j
@Aspect
@Component
@RequiredArgsConstructor
public class CacheComboboxAspect {

    private final ComboboxService comboboxService;

    @AfterReturning(pointcut = "@annotation(cacheCombobox)", returning = "result")
    public void cacheCombobox(JoinPoint joinPoint, CacheCombobox cacheCombobox, Object result) {
        // 获取方法参数
        Object[] args = joinPoint.getArgs();
        String cacheName = cacheCombobox.cacheName();
        String parentKeyField = cacheCombobox.parentKeyField();
        String keyField = cacheCombobox.keyField();
        String valueField = cacheCombobox.valueField();
        String parentKeyFieldValue = null;
        String keyFieldValue = null;
        String valueFieldValue = null;

        if (joinPoint.getSignature().getName().startsWith("delete")) {
            try {
                List<String> keyValues = getKeyValuesFromArgs(joinPoint.getArgs(), keyField);
                keyValues.forEach(key -> {
                    CacheUtils.evict(cacheName, key);
                    comboboxService.syncLabelCache(cacheName,  key);
                });
            } catch (Exception e) {
                log.error("处理缓存字段时出错", e);
            }
        } else {
            try {
                parentKeyFieldValue = getValueFromBo(args, parentKeyField);
                keyFieldValue = getValueFromBo(args, keyField);
                valueFieldValue = getValueFromBo(args, valueField);
                // 下拉框缓存 global:combobox:task:=null:id=1887359915875491842:title=巴斯夫OAuth2.0申请问答
                log.info("下拉框缓存 {}:{}={}:{}={}:{}={}", cacheName,
                    parentKeyField, parentKeyFieldValue, keyField, keyFieldValue, valueField, valueFieldValue);
                if (keyFieldValue != null && valueFieldValue != null) {
                    CacheUtils.put(cacheName, keyFieldValue, valueFieldValue);
                }
                // 缓存父子级
                if (parentKeyFieldValue != null) {
                    CacheUtils.put(cacheName + ":" + parentKeyFieldValue, keyFieldValue, valueFieldValue);
                }
                // 缓存key-label
//                CacheUtils.put("key_label", keyFieldValue, valueFieldValue);
                comboboxService.syncLabelCache(cacheName, parentKeyField, keyField, valueField, parentKeyFieldValue, keyFieldValue, valueFieldValue);
            } catch (Exception e) {
                log.error("处理缓存字段时出错", e);
            }
        }
        // todo 保存到数据库
    }

    /**
     * 从实体对象中获取指定字段的值
     */
    private String getFieldValue(Object entity, String fieldName) throws Exception {
        java.lang.reflect.Field field = entity.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        return field.get(entity).toString();
    }

    /**
     * 从Bo对象中获取指定字段的值
     */
    private String getValueFromBo(Object[] args, String keyField) throws Exception {
        if (StringUtils.isBlank(keyField)) return null;
        for (Object arg : args) {
            if (arg.getClass().getSimpleName().endsWith("Bo")) {
                java.lang.reflect.Field field = arg.getClass().getDeclaredField(keyField);
                field.setAccessible(true);
                return field.get(arg).toString();
            }
        }
        return null;
    }

    /**
     * 从参数列表中获取指定字段的值，并返回一个字符串列表
     */
    private List<String> getKeyValuesFromArgs(Object[] args, String keyField) throws Exception {
        List<String> keyValues = new ArrayList<>();
        for (Object arg : args) {
            if (arg != null) {
                if (arg instanceof Collection) {
                    for (Object item : (Collection<?>) arg) {
                        keyValues.add(Objects.toString(item));
                    }
                }
            }
        }
        return keyValues;
    }

    /**
     * 从对象中获取指定字段的值
     */
    private String getKeyValue(Object obj, String keyField) throws Exception {
        java.lang.reflect.Field field = obj.getClass().getDeclaredField(keyField);
        field.setAccessible(true);
        return field.get(obj).toString();
    }
}
